package com.supermap.wzhy.module.fr.service;

import com.supermap.wzhy.entity.TMicroIdenmeta;
import com.supermap.wzhy.entity.TMicroTablemeta;
import com.supermap.wzhy.module.context.CodeMapServer;
import com.supermap.wzhy.module.context.CodeMapService;
import com.supermap.wzhy.module.data.dao.MicroIdenmetaDao;
import com.supermap.wzhy.module.data.dao.MicroTablemetaDao;
import com.supermap.wzhy.module.fr.dao.FrDao;
import com.supermap.wzhy.module.mlk.service.MlkTsFrService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import javax.naming.NamingException;
import java.text.SimpleDateFormat;
import java.util.*;

/**
 * Created by Administrator on 2016/12/28 0028.
 * 法人推送名录库
 */
@Service
public class FrTsMlkService {
    @Autowired
    FrDao frDao;
    @Autowired
    MicroTablemetaDao microTablemetaDao;
    @Autowired
    MicroIdenmetaDao microIdenmetaDao;

    @Autowired
    MlkTsFrService mlkTsFrService;

    /**
     * 根据选择的作用对象表，查询相关范围内数据，推送至名录库目标表
     * @param actionTbls 作用对象表集合
     * @param startTime 开始时间
     * @param endTime 截止时间
     */
    public void toMlk(List<String> actionTbls,Date startTime,Date endTime){
        //参数预处理
        SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        String startTimeStr = "";
        String endTimeStr = "";
        if (startTime == null) {
            startTimeStr = "2000-1-1 00:00:00";
        }else{
            startTimeStr=formatter.format(startTime);
        }
        if (endTime == null) {
            endTimeStr = formatter.format(new Date());
        }else{
            endTimeStr = formatter.format(endTime);
        }

        String where=" where S_EXT_TIMESTAMP>= to_date(startTimeStr,'yyyy-mm-dd hh24:mi:ss') and S_EXT_TIMESTAMP < to_date(endTimeStr,'yyyy-mm-dd hh24:mi:ss') ";
        //根据目标对象表查询表指标
        List<TMicroTablemeta> tblMetas=microTablemetaDao.findBatchTableName(actionTbls);
        //构建查询sql
        Map<String,String> actionTblToSql=new HashMap<>();
        //tbl-idencode-iden
        Map<String,Hashtable<String,TMicroIdenmeta>> actionTblToIdens=new HashMap<>();
        for(TMicroTablemeta tblMeta:tblMetas){
            Set<TMicroIdenmeta> idenmetas=tblMeta.getTMicroidenmetas();
            Hashtable<String,TMicroIdenmeta> codeToIden=new Hashtable<>();
            for(TMicroIdenmeta idenmeta:idenmetas){
                codeToIden.put(idenmeta.getIdenCode(),idenmeta);
            }
            actionTblToIdens.put(tblMeta.getTableName(),codeToIden);
        }
        for(Map.Entry<String,Hashtable<String,TMicroIdenmeta>> entry:actionTblToIdens.entrySet()){
            String tblName=entry.getKey();
            Set<String> idens=entry.getValue().keySet();
            String queryColumnStr=StringUtils.collectionToDelimitedString(idens,",");
            actionTblToSql.put(tblName,"select "+queryColumnStr+" from "+tblName+where);
        }
        //查询结果键值对 tableName-value,顺序按照查询顺序
        Map<String,List<Object[]>> queryResult=new HashMap<>();
        for(Map.Entry<String,String> entry:actionTblToSql.entrySet()){
            String tblName=entry.getKey();
            String sql=entry.getValue();
            List result=this.frDao.query(sql);
            List<Object[]> idenToValue=new ArrayList<>();
            queryResult.put(tblName,idenToValue);
            int size=result.size();
            if(size>0){
                for(int i=0;i<size;i++){
                    idenToValue.add((Object[])result.get(i));
                }
            }
        }
        //作用表至目标表之间的指标映射，并构建插入sql,目标表的表名是否同作用表名一致？暂时考虑为一致
        for(Map.Entry<String,List<Object[]>> entry:queryResult.entrySet()){
            String actionTblName=entry.getKey();
            List<Object[]> values=entry.getValue();
            List<String> sqls=this.targetSqlFromCodeAndValue(actionTblToIdens,actionTblName,values);
            //逐表批量推送
            Map successInfo=this.mlkTsFrService.saveFromFrSql(sqls);
        }

        //释放内存
        queryResult.clear();
        queryResult=null;
        actionTblToIdens.clear();
        actionTblToIdens=null;
    }

    /**
     * 查询出的作用表数据，需要根据列类型进行一个数据库类型转换
     * @param actionTblToIdens 作用表的列信息，包含类型，精度等
     * @param tableName 作用表名
     * @param values 查询出的Object值集合
     * @return
     */
    private List<String> targetSqlFromCodeAndValue(Map<String,Hashtable<String,TMicroIdenmeta>> actionTblToIdens,String tableName,List<Object[]> values){
        Hashtable<String,TMicroIdenmeta> codeToIden=actionTblToIdens.get(tableName);
        //获取指标映射记录
        Hashtable<String,String> info=this.getMapInfo(tableName);
        //插入列集合
        List<String> insertColumns=new ArrayList<>();
        //插入值类型关系
        Map<Integer,Integer> valueType=new HashMap<>();
        Set<String> actionCodes=codeToIden.keySet();
        int i=0;
        for (Iterator it = actionCodes.iterator(); it.hasNext(); i++) {
            String actionCode = (String) it.next();
            TMicroIdenmeta idenmeta=codeToIden.get(actionCode);
            String targetCode=actionCode;
            if(info.containsKey(actionCode)){
                targetCode=info.get(actionCode);
            }
            insertColumns.add(targetCode);
            int type=idenmeta.getIdenType();
            valueType.put(i,type);
        }
        //插入值集合，构建行sql
        List<String> sqls=new ArrayList<>();
        for(Object[] row:values){
            List<String> insertValues=new ArrayList<>();
            int length=row.length;
            for(int j=0;j<length;j++){
                int type=valueType.get(j);
                String cellValue=String.valueOf(row[i]);
                if(type==1){//假设1是字符串
                    cellValue="'"+cellValue+"'";
                }
                insertValues.add(cellValue);
            }
            String insertColumnStr=StringUtils.collectionToDelimitedString(insertColumns,",");
            String insertValueStr=StringUtils.collectionToDelimitedString(insertValues,",");
            String sql="insert into "+tableName+"("+insertColumnStr+") values("+insertValueStr+")";
            sqls.add(sql);
        }
        return sqls;
    }

    /**
     * 获取作用表的指标映射关系
     * @param tablename 作用表名
     * @return
     */
    private Hashtable<String,String> getMapInfo(String tablename){
        CodeMapServer server=new CodeMapServer();
        try {
            CodeMapService service=(CodeMapService)server.getContext().lookup("StubService");
            Map<String,Hashtable<String,String>> codeMapInfo=service.getInfo();
            if(codeMapInfo.containsKey(tablename)){
                return codeMapInfo.get(tablename);
            }
        } catch (NamingException e) {
            e.printStackTrace();
        }
        return null;
    }
}
